package com.jmx.manager.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sun.management.GarbageCollectorMXBean;
import com.sun.management.HotSpotDiagnosticMXBean;
import com.sun.management.OperatingSystemMXBean;
import org.springframework.stereotype.Service;

import javax.management.*;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
import java.lang.management.*;
import java.util.Set;

@Service
public class JmxService {

    public JMXConnector getJMXConnector(String host, int port) throws Exception {
        String jmxURL = "service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi";
        JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);
        JMXConnector conn = JMXConnectorFactory.connect(serviceURL);
        return conn;
    }

    public MBeanServerConnection getMBeanServer(String host, int port) throws Exception {
        JMXConnector jmxConnector = getJMXConnector(host, port);
        return jmxConnector.getMBeanServerConnection();
    }

    public Set<ObjectInstance> getMBeans(MBeanServerConnection mbs) throws Exception {
        return mbs.queryMBeans(null, null);
    }

    /**
     * 获取构造器
     * @param mbs
     * @return
     * @throws Exception
     */
    public MBeanConstructorInfo[] getMBeanConstructorInfo(MBeanServerConnection mbs, ObjectName objectName) throws Exception {
        MBeanInfo mBeanInfo = mbs.getMBeanInfo(objectName);

        // 构造器
        MBeanConstructorInfo[] constructors = mBeanInfo.getConstructors();
        return constructors;
    }

    /**
     * 获取变量属性
     * @param mbs
     * @return
     * @throws Exception
     */
    public MBeanAttributeInfo[] getMBeanAttributeInfo(MBeanServerConnection mbs, ObjectName objectName) throws Exception {
        MBeanInfo mBeanInfo = mbs.getMBeanInfo(objectName);

        // 变量
        MBeanAttributeInfo[] attributes = mBeanInfo.getAttributes();
        return attributes;
    }

    /**
     * 获取变量属性的值
     * @param mbs
     * @param attributeInfo
     * @return
     * @throws Exception
     */
    public Object getMBeanAttributeValue(MBeanServerConnection mbs, ObjectName objectName, MBeanAttributeInfo attributeInfo) throws Exception {
        return mbs.getAttribute(objectName, attributeInfo.getName());
    }

    /**
     * 获取方法
     * @param mbs
     * @return
     * @throws Exception
     */
    public MBeanOperationInfo[] getMBeanOperationInfo(MBeanServerConnection mbs, ObjectName objectName) throws Exception {
        MBeanInfo mBeanInfo = mbs.getMBeanInfo(objectName);

        // 方法
        MBeanOperationInfo[] operations = mBeanInfo.getOperations();
        return operations;
    }

    //Java 虚拟机线程系统的管理接口 ThreadMXBean
    public JSONObject getThreadMXBean(MBeanServerConnection mbs) throws Exception {
        com.sun.management.ThreadMXBean threadMXBean = ManagementFactory.newPlatformMXBeanProxy
                (mbs, ManagementFactory.THREAD_MXBEAN_NAME, com.sun.management.ThreadMXBean.class);

        JSONObject jsonObject = (JSONObject) JSON.toJSON(threadMXBean);
        ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds());
        jsonObject.put("threadInfos", threadInfos);

        return jsonObject;
    }

    // 根据线程ID，获取分配的内存
    public long[] getThreadMXBeanBytes(MBeanServerConnection mbs, long[] ids) throws Exception {
        com.sun.management.ThreadMXBean threadMXBean = ManagementFactory.newPlatformMXBeanProxy
                (mbs, ManagementFactory.THREAD_MXBEAN_NAME, com.sun.management.ThreadMXBean.class);
        long[] threadAllocatedBytes = threadMXBean.getThreadAllocatedBytes(ids);

        return threadAllocatedBytes;
    }

    // dump线程
    public ThreadInfo[] getThreadMXBeanDump(MBeanServerConnection mbs) throws Exception {
        com.sun.management.ThreadMXBean threadMXBean = ManagementFactory.newPlatformMXBeanProxy
                (mbs, ManagementFactory.THREAD_MXBEAN_NAME, com.sun.management.ThreadMXBean.class);

        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true);
        return threadInfos;
    }

    // 加载的class
    public ClassLoadingMXBean getClassLoadingMXBean(MBeanServerConnection mbs) throws Exception {
        ClassLoadingMXBean classLoadingMXBean = ManagementFactory.newPlatformMXBeanProxy
                (mbs, ManagementFactory.CLASS_LOADING_MXBEAN_NAME, ClassLoadingMXBean.class);
        return classLoadingMXBean;
    }

    //Java 虚拟机的运行时系统的管理接口。 RuntimeMXBean
    public RuntimeMXBean getRuntimeMXBean(MBeanServerConnection mbs) throws IOException {
        RuntimeMXBean run = ManagementFactory.newPlatformMXBeanProxy
                (mbs, ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
        return run;
    }

    //用于操作系统的管理接口，Java 虚拟机在此操作系统上运行 OperatingSystemMXBean
    public OperatingSystemMXBean getOperatingSystemMXBean(MBeanServerConnection mbs) throws IOException {
        OperatingSystemMXBean op = ManagementFactory.newPlatformMXBeanProxy
                (mbs, ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class);
        return op;
    }

    //内存池的管理接口。内存池表示由 Java 虚拟机管理的内存资源，
    //由一个或多个内存管理器对内存池进行管理 MemoryMXBean
    public MemoryPoolMXBean getMemoryPoolMXBean(MBeanServerConnection mbs) throws IOException {
        MemoryPoolMXBean list = ManagementFactory.newPlatformMXBeanProxy
                (mbs, "java.lang:name=Compressed Class Space,type=MemoryPool", MemoryPoolMXBean.class);
        return list;
    }

    //Java 虚拟机内存系统的管理接口。 MemoryMXBean
    public MemoryMXBean getMemoryMXBean(MBeanServerConnection mbs) throws IOException {
        MemoryMXBean list = ManagementFactory.newPlatformMXBeanProxy
                (mbs, ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);
        return list;
    }

    public HotSpotDiagnosticMXBean getHotSpotDiagnosticMXBean(MBeanServerConnection mbs) throws IOException {
        HotSpotDiagnosticMXBean list = ManagementFactory.newPlatformMXBeanProxy
                (mbs, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
        return list;
    }
}
